import { createRequire } from 'node:module'
import { readFileSync, existsSync } from 'node:fs'
import { transformVueTemplateToSolid } from './index.js'

const require = createRequire(import.meta.url)

const indexTemplate = `
import pc from './pc.vue'

export default function (props) {
  const { tiny_mode = 'pc' } = props

  const S = {
    pc
  }[tiny_mode]

  return S(props)
}
`

const pcTemplate = `
import { renderless } from '@opentiny/vue-renderless/<%=NAME%>/vue'
import { <%=USECOMMONS%> } from '@opentiny/solid-common'
import '@opentiny/vue-theme/<%=NAME%>/index.less'
<%=IMPORTICONS%>

const useIcons = <%=USEICONS%>
const $constants = <%=CONSTANTS%>

export default function (props) {
  const { children, <%=USEPROPS%> } = props
  const { state, <%=USEAPI%> } = useSetup({
    props: mergeProps({<%=DEFAULTPROPS%>}, props),
    renderless,
    constants: $constants,
  })

  return (<%=JSX%>)
}
`

const matchComponentRegx = /vue\/src\/([a-z]+)\/src/
const fundProps = (code, findStr) => {
  let findIndex = code.indexOf(findStr)
  let props = ''

  if (~findIndex) {
    const endStr = 'export '
    let constantsPart = code.substring(findIndex + findStr.length, code.length)
    props = constantsPart.substring(0, constantsPart.indexOf(endStr))
  }

  return props
}

const getSvgContent = (svg) => {
  return svg.substring(svg.indexOf('>') + 1, svg.length)
}

export default function vueTemplate2Jsx() {
  const defaultMap = {}

  return {
    name: '@opentiny/vue-plugin-vue2jsx',
    enforce: 'pre',
    transform(code, id) {
      if (id.includes('vue-icon/src')) {
        const svgName = code.match(/([a-z-]+)\.svg/)

        if (svgName && svgName[0]) {
          const svgPath = require.resolve(`@opentiny/vue-theme/svgs/${svgName[0]}`)
          if (existsSync(svgPath)) {
            let svgContent = readFileSync(svgPath, { encoding: 'utf-8' })

            if (svgContent.includes('<!--')) {
              svgContent = svgContent.replace(/<!--[\s\S]+-->/, '')
            }

            if (svgContent.includes('<?xml')) {
              svgContent = getSvgContent(svgContent)
            }

            if (svgContent.includes('<!DOCTYPE')) {
              svgContent = getSvgContent(svgContent)
            }

            if (svgContent.includes('<style')) {
              svgContent = svgContent.replace(/<style[\s\S]+<\/style>/, '')
            }

            return `export default function(props) {
              return (<svg style={props.style} xmlns="http://www.w3.org/2000/svg" onClick={props.onClick} viewBox="0 0 24 24" xml:space="preserve" class={'tiny-svg svgs-icon ' + props.class}>
                ${getSvgContent(svgContent)}  
              )
            }`
          }
        }

        return code
      }

      if (id.includes(`src/index.ts`) && !id.includes(`common/src/index.ts`)) {
        const componentMatchs = id.match(matchComponentRegx)
        if (componentMatchs?.[1]) {
          let constants = fundProps(code, '$constants =') || '{}'
          let propsContent = fundProps(code, 'Props =') || fundProps(code, 'props :')
          let props = {}

          if (propsContent) {
            const propsContentParts = propsContent.split(/\n/)
            propsContentParts.forEach((item, index) => {
              if (item.indexOf('type:') && ['Boolean', 'String', 'Number'].some((type) => item.includes(type))) {
                const name = propsContentParts[index - 1].replace(/\W/g, '')
                let value = propsContentParts[index + 1]

                if (name && value.includes('default:')) {
                  const type = /['"]/.test(value) ? 'Char' : 'Other'
                  value = value.replace('default:', '').replace(/["|'|\s,]/g, '')
                  props[name] = { type, value }
                }
              }
            })
          }

          defaultMap[componentMatchs[1]] = {
            $constants: constants,
            $props: props
          }
        }

        return indexTemplate
      }

      if (id.includes('pc.vue')) {
        const componentMatchs = id.match(matchComponentRegx)
        if (componentMatchs?.[1]) {
          const mapData = defaultMap[componentMatchs[1]]
          const pcComponent = transformVueTemplateToSolid(pcTemplate, code, componentMatchs[1], mapData)
          delete defaultMap[componentMatchs[1]]
          return pcComponent
        }
      }
    }
  }
}
